# -*- coding: utf-8 -*-
import time
import base64
import requests
import json

from collections import OrderedDict
from django.conf import settings
from Crypto.Cipher import PKCS1_v1_5
from Crypto.Hash import SHA
from Crypto.Signature import PKCS1_v1_5 as sign_pkcs1_v1_5
from Crypto.PublicKey import RSA

from async import async_job
from common.channel.pay import check_channel_order
from common.order import db as order_db
from common.order.model import PAY_STATUS
from common.utils import track_logging
from common.utils.exceptions import SignError, NotPayOrderError, ProcessedPayOrderError, NotResponsePayIdError
from common.utils.ip_address import check_valid_ip_address

_LOGGER = track_logging.getLogger(__name__)

APP_CONF = {
    'JA38A490628A2': {
        'pri_key': """
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC2AVjpuujbXIA0
+85Ip00rCkA3TSAPlJ5jieBaU6MYTbRjAJ46hStc93Qz4UTSnU3tQa8uNdVn5ifN
QZYMGJSMElmVzbW7bDL2+xuUy0jgFq9WoZDxk4Z9hZA5cslT1aaKMh7SDf8S2whp
UfwqcW4qtMuEXEnnj+xfQz8soC/Mc3zU+uAFeiGU8PO/qT007kV/JxqdRAnDwrup
ShEQBCfWbs3BVpcjbHaO+l7I/iEqGwbPPMEIAYyk9RZ1JCQ6PJw0zB5/S5jvV0Kh
3uFxXFmRrlUBUuTaTBiUryZjCGBOB5lk+bFMb3nZJcEyHds+9eNkbV2yShLEyD/F
rkbA9DqrAgMBAAECggEBAJpVeCTydsSUoq7LG7hmDbzCe4OpZddwagL0Bofxxio0
shMFkicDh6rUtvfLPQXvmAXpHfhsc+Mfun6F8AufyE8ivE6YWlNsw6bFdjTtUIWd
Ft+6L2N6ep/z40GjwW7Si99B8vqiHbrKe0570/3Vo9qY5r79VzoBxClfp7FawE13
66QnjES3ueA8IN20cI69oK7dVKP/5W8ULnRIE0ChgNcnH3vfO+tBOLd5S7iN4VZ9
fSJaGcsBckyGnyJu9ac3uqNTOG/hKuyMrXJSoHSmPw2fnAIiahtU3YbYi4FUz49X
7DLdg5mmCe+xXssYtz55wVfxJpUDahwaVC4BBm3UoZECgYEA9dOKAKuU6gnBBCCt
VnDchcN4c+8xwRYGEGcKML+FCNG6X33LKXOL0fiZi+l9jqcH5BkHFQxeDVYrhu5L
nqCFfqGuJXe8h3/IzFxcGJPYSWtezhHRQ+e6/Zx2JTePJUi5I87jk54HrkCBl7y+
GITGbgi5xEC9zCVGXIRt//SJJOkCgYEAvYmkWnXHZDMmwTOZZfYSlwqKsKR1rXFJ
dhLxP8XV+JCAA7D19xbL5lVjjyJmg3cd72G0uXhwNN7fGjrVJkRaphp8ZPcYy7ZX
to+CnX5KYsOhcBtO4b1oRgTp1IKFqzLlM6FwMehsC2E8oJ5hFyMLW5J2RRn1flwo
VJVy33ljtnMCgYB6WyxZYQ3h37D+yPT+DXb17XFK40e0f63NBDyCPxGMbjeByC8T
FrwFauOiTDl+g4zd78cipuE5aiaIJpvk/Kj1eqwfYhWoq+XaMi503UHOaW7qytuK
HRFpojL8G0dYm3XraNLFaucPyHO4fu1vbscFhbpRAJh3wCXhbtkBiUmp4QKBgGuo
R+Nd7OCcMVIiJeqFR+/k+/vznifjJi/b+I4ZqDzkjuIJ3Nv5Zd2x+LfveT0JJsa2
v7ltkIZnZV/3tORkhPy+JJQQylPDgbTfdPhSKJxKtGMCD98m/5ht6AdeD+C7KvcV
pq2ib+RS2eX9r/Y9YJEl8umzIf8hB4Nr0/DdeWbDAoGBAKUv+sHd+3uRBlg2QtEi
BVoVrZF1oVnxKT7rbbuvdMhWv5RXuRsaGLWGCkUUsWAmE+dL6AVXEC1xfZ9WJacc
HMLU7jNKZmhahmo8FAYtkLFaTCFg9BP1g+KJ9n2ngxs6FldmFfS0/9223eCKQycd
E7oZUERMQ/WrJER5taOeYeXT
""",
        'pub_key': """
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtgFY6bro21yANPvOSKdN
KwpAN00gD5SeY4ngWlOjGE20YwCeOoUrXPd0M+FE0p1N7UGvLjXVZ+YnzUGWDBiU
jBJZlc21u2wy9vsblMtI4BavVqGQ8ZOGfYWQOXLJU9WmijIe0g3/EtsIaVH8KnFu
KrTLhFxJ54/sX0M/LKAvzHN81PrgBXohlPDzv6k9NO5FfycanUQJw8K7qUoREAQn
1m7NwVaXI2x2jvpeyP4hKhsGzzzBCAGMpPUWdSQkOjycNMwef0uY71dCod7hcVxZ
ka5VAVLk2kwYlK8mYwhgTgeZZPmxTG952SXBMh3bPvXjZG1dskoSxMg/xa5GwPQ6
qwIDAQAB
""",
        'sys_pub_key': """
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArNK2a7J7xZ9axCqn7o/t
Gf3vZCZeDwmcxPgjO/dvcKeMmxP+3bVt4bBYVKbRtkbVZMrVki4biRQJKUOIouCE
APGRRr2xTXecktFnLhdxawHnhi9iGLjcl1bN17I+roQojn+1Vmcbq+2aU9Vz6rQT
tU4q/v9vcElimCPtbFwrRcwLBPYJvxDbTMklGikeS+D1jW3q5q385PiBPOGNHviO
h93xVOyWvWkmc36QA3wj9glZ9BBSmDCJnvDyH+Siky4NfrEGEBjt4E8zywjT4ADw
yZ1tTjoY0kUUG9DuLU0+f8fYLKcaVLoBGkwT9tl7s1IzwNqzfpaLqzCB+yXsmpgh
2wIDAQAB""",
        'gateway': 'https://api.yoopayment.com/rsa/deposit',
        'query_gateway': 'https://api.yoopayment.com/rsa/query-order',
    }
}


def _get_pay_type(service):
    if service == '	Wechat_QR':  # 微信扫码
        return '2'
    if service == '	Alipay_QR':  # 支付宝扫码
        return '3'
    elif service == 'Alipay_WAP':  # 支付宝h5
        return '9'
    elif service == 'UnionPay_WAP':  # 银联快捷
        return '13'
    elif service == 'quickpay_QR':  # 云闪付
        return '15'
    else:
        return '3'


# 私钥
def _get_pri_key(mch_id):
    return APP_CONF[mch_id]['pri_key']


# 公钥
def _get_pub_key(mch_id):
    return APP_CONF[mch_id]['pub_key']


# 系统(通道)公钥
def _get_sys_pub_key(mch_id):
    return APP_CONF[mch_id]['sys_pub_key']


def _get_gateway(mch_id):
    return APP_CONF[mch_id]['gateway']


def _get_query_gateway(mch_id):
    return APP_CONF[mch_id]['query_gateway']


# 加签
def rsa_sign(data, pri_key):
    key_bytes = base64.b64decode(pri_key)
    pri = RSA.importKey(key_bytes)
    cipher = SHA.new(data)
    sign = base64.b64encode(sign_pkcs1_v1_5.new(pri).sign(cipher))
    return sign


# 验签
def rsa_verify(sign, message, pub_key):
    key_bytes = base64.b64decode(pub_key)
    pub = RSA.importKey(key_bytes)
    cipher = SHA.new(message)
    t = sign_pkcs1_v1_5.new(pub).verify(cipher, base64.b64decode(sign))
    if not t:
        _LOGGER.info("jiefupay sign not pass")
        raise SignError('jiefupay sign not pass')


# 加密
def rsa_encrypt(biz_content, public_key):
    key_bytes = base64.b64decode(public_key)
    _p = RSA.importKey(key_bytes)
    biz_content = biz_content.encode('utf-8')
    # 2048bit key
    default_encrypt_length = 245
    len_content = len(biz_content)
    if len_content < default_encrypt_length:
        return base64.b64encode(PKCS1_v1_5.new(_p).encrypt(biz_content))
    offset = 0
    params_lst = []
    while len_content - offset > 0:
        if len_content - offset > default_encrypt_length:
            params_lst.append(PKCS1_v1_5.new(_p).encrypt(biz_content[offset:offset + default_encrypt_length]))
        else:
            params_lst.append(PKCS1_v1_5.new(_p).encrypt(biz_content[offset:]))
        offset += default_encrypt_length
    target = ''.join(params_lst)
    return base64.b64encode(target)


# 解密
def rsa_decrypt(biz_content, private_key):
    key_bytes = base64.b64decode(private_key)
    _pri = RSA.importKey(key_bytes)
    biz_content = base64.b64decode(biz_content.encode('utf-8'))
    # 2048bit key
    default_length = 256
    len_content = len(biz_content)
    print len_content
    if len_content < default_length:
        return PKCS1_v1_5.new(_pri).decrypt(biz_content, 'ERROR')
    offset = 0
    params_lst = []
    while len_content - offset > 0:
        print '2'
        if len_content - offset > default_length:
            params_lst.append(
                PKCS1_v1_5.new(_pri).decrypt(biz_content[offset: offset + default_length], 'ERROR'))
        else:
            params_lst.append(PKCS1_v1_5.new(_pri).decrypt(biz_content[offset:], 'ERROR'))
        offset += default_length
    target = ''.join(params_lst)
    return target


# 创建支付订单
def create_charge(pay, pay_amount, info):
    app_id = info['app_id']
    service = info.get('service')
    parameter_dict = OrderedDict((
        ('bank_code', ''),
        ('service_type', _get_pay_type(service)),
        ('amount', '%.2f' % pay_amount),
        ('merchant_user', 'none'),
        ('risk_level', '1'),
        ('merchant_order_no', pay.id),
        ('platform', 'PC'),
        ('callback_url', '{}/pay/api/{}/jiefupay/{}'.format(
            settings.NOTIFY_PREFIX, settings.NOTIFY_PATH, app_id)),
        ('note', '')
    ))
    json_data = json.dumps(parameter_dict, ensure_ascii=False)
    _LOGGER.info('jiefupay create data:%s' % json_data)
    # 秘文
    rsa_data = rsa_encrypt(json_data, _get_sys_pub_key(app_id))
    # 签名
    sign = rsa_sign(rsa_data, _get_pri_key(app_id))
    # 通讯数据
    request_text = OrderedDict((
        ('merchant_code', app_id),
        ('data', rsa_data),
        ('sign', sign),
    ))
    headers = {'Content-Type': 'application/x-www-form-urlencoded'}
    response = requests.post(_get_gateway(app_id), data=request_text, headers=headers, timeout=5)
    response_data = json.loads(response.text.replace('\\r', ''))
    if str(response_data['status']) == '1':
        response_sign = response_data['sign']
        response_data = response_data['data']
        # 验签
        rsa_verify(response_sign, response_data, _get_sys_pub_key(app_id))
        # 解密
        data_str = rsa_decrypt(response_data, _get_pri_key(app_id))
        data = json.loads(data_str)
        url = data['qr_image_url'] if data['qr_image_url'] and str(data['qr_image_url']) != 'null' else data[
            'transaction_url']
        _LOGGER.info('jiefupay response url: %s', url)
        return {'charge_info': url}
    return {'charge_info': response_data['error_code']}


# OK
def check_notify_sign(request, app_id):
    _LOGGER.info("jiefupay notify body: %s", request.body)
    res_data = dict(request.POST.items())
    rsa_verify(res_data['sign'], res_data['data'], _get_sys_pub_key(app_id))
    data_str = rsa_decrypt(res_data['data'], _get_pri_key(app_id))
    data = json.loads(data_str)

    _LOGGER.info("jiefupay notify data: %s, order_id is: %s", data, data['merchant_order_no'])
    pay_id = data['merchant_order_no']
    check_valid_ip_address(str(request.META['REMOTE_ADDR']), pay_id)
    if not pay_id:
        _LOGGER.error("jiefupay fatal error, out_trade_no not exists, data: %s", data)
        raise NotResponsePayIdError('jiefupay event does not contain pay ID')

    pay = order_db.get_pay(int(pay_id))
    if not pay:
        raise NotPayOrderError('jiefupay pay_id: %s invalid' % pay_id)
    if pay.status != PAY_STATUS.READY:
        raise ProcessedPayOrderError('jiefupay pay %s has been processed' % pay_id)

    mch_id = pay.mch_id  # 商户编号
    trade_status = ''
    trade_no = data['merchant_order_no']
    total_fee = float(data['amount'])
    extend = {
        'trade_status': trade_status,
        'trade_no': trade_no,
        'total_fee': total_fee,
    }

    check_channel_order(pay_id, total_fee, app_id)
    # 只有支付成功才回调
    _LOGGER.info('jiefupay check order success, mch_id:%s pay_id:%s' % (mch_id, pay_id))
    order_db.add_pay_success(mch_id, pay_id, total_fee, trade_no, extend)
    # async notify
    async_job.notify_mch(pay_id)


def query_charge(pay_order, app_id):
    """ 查询订单 """
    pay_id = pay_order.id
    parameter_dict = OrderedDict((
        # 要查询订单的订单号
        ('merchant_order_no', str(pay_id)),
    ))
    json_data = json.dumps(parameter_dict, ensure_ascii=False)
    _LOGGER.info('jiefupay create data:%s' % json_data)
    # 秘文
    rsa_data = rsa_encrypt(json_data, _get_sys_pub_key(app_id))
    # 签名
    sign = rsa_sign(rsa_data, _get_pri_key(app_id))
    # 通讯数据
    request_text = OrderedDict((
        ('merchant_code', app_id),
        ('data', rsa_data),
        ('sign', sign),
    ))
    headers = {'Content-Type': 'application/x-www-form-urlencoded'}
    response = requests.post(_get_query_gateway(app_id), data=request_text, headers=headers, timeout=5)
    response_data = json.loads(response.text)
    if str(response_data['status']) == '1':
        response_sign = response_data['sign']
        response_data = response_data['data']
        # 验签
        rsa_verify(response_sign, response_data, _get_sys_pub_key(app_id))
        # 解密
        data_str = rsa_decrypt(response_data, _get_pri_key(app_id))
        data = json.loads(data_str)
        _LOGGER.info('jiefupay query response data: %s', data)
        trade_status = data['trans_status']
        total_fee = 0
        # P：正在申请中还未支付，没有返回amount
        if trade_status != 'P':
            total_fee = float(data['amount'])
        trade_no = parameter_dict['merchant_order_no']
        extend = {
            'trade_status': trade_status,
            'trade_no': trade_no,
            'total_fee': total_fee,
        }
        check_channel_order(pay_id, total_fee, app_id)
        # S：支付成功
        if trade_status == 'S':
            _LOGGER.info('jiefupay query order success, mch_id:%s pay_id:%s' % (pay_order.mch_id, trade_no))
            order_db.add_pay_success(pay_order.mch_id, pay_order.id, total_fee, trade_no, extend)
            async_job.notify_mch(pay_order.id)
        else:
            _LOGGER.info('jiefupay query order success, but not pay success, pay pay_id: %s,trade_status:%s'
                         % (trade_no, trade_status))
    else:
        _LOGGER.warn('jiefupay data error, error_code: %s', response_data['error_code'])
